//
//  BasicCalculatorView.m
//  iCalculator
//
//  Created by Stephen Houser on 9/9/07.
//  Copyright 2007 __MyCompanyName__. All rights reserved.
//

#import "CalculatorApp.h"
#import "CalculatorEngine.h"
#import "BasicKeypad.h"
#import "ScientificKeypad.h"
#import "BasicCalculatorView.h"


// This needs to be moved to a preferences list or something "very nice" like that.
// I dont like long-term hardcoded things. But, hey, I'm not an Objective-C god 
// so cut me some slack.
#define DISPLAY_HTML @"<span style=\"color:#124564;text-align:right;display:block;font-family:helvetica;font-size:64px;font-weight:normal;width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;letter-spacing:-2px;\">%@</span>"

@implementation BasicCalculatorView

/*
 * Initialization of the BasicCalculatorView
 * Sets up the controller and engine this view is connected to.
 * Sets up the user interface elements.
 */
- (id) initWithFrame: (CGRect) frame 
		withController:(CalculatorApp *) theController 
		withEngine: (CalculatorEngine *) theEngine
		withType: (int) calcType {

	self = [super initWithFrame: frame];
	
	controller = theController;
	engine = theEngine;
	display = [[NSMutableString alloc] init];
	resetDisplay = YES;
	
	// The result text is just 89 pixels at the top.
	// hardcoded for now.
	struct CGRect resultRect = frame;
	resultRect.size.height = 89.0f;
	//NSLog(@"resultRect is %f, %f, %f, %f", resultRect.origin.x, resultRect.origin.y, resultRect.size.width, resultRect.size.height);

	// result text field up there at the top -- like a normal calculator
	resultDisplay = [[UITextView alloc] initWithFrame: resultRect];
	[resultDisplay setEditable: NO];
	[resultDisplay setScrollingEnabled: NO];
	//[resultText setTextSize: 64];
	[self addSubview: resultDisplay]; 
	
	// The keypad is below the results, 90 pixels, again hardcoded for now.
	struct CGRect keypadRect = frame;
	keypadRect.origin.y = resultRect.size.height;
	
	if (calcType == 0) {
		keypad = [[BasicKeypad alloc] initWithFrame: keypadRect withController: self];
		[keypad setImage: [UIImage imageNamed: @"CalculatorBackground.png"]];
		[self addSubview: keypad];
	} else {
		keypad = [[ScientificKeypad alloc] initWithFrame: keypadRect withController: self];
		[keypad setImage: [UIImage imageNamed: @"ScientificBackground.png"]];
		[self addSubview: keypad];
	}
	
	return self;
}

/*
 * Updates the results view -- the dislay of the calculator.
 */
- (void) updateView {
	//NSLog(@"BasicCalculatorView updateView [%@]", display);
	[resultDisplay setHTML: [NSString stringWithFormat: DISPLAY_HTML, display]];
	[resultDisplay setNeedsDisplay];
}

/*
 * Handle incoming commands, keypresses, etc. from our children components.
 * This is in reality the dispatcher for the view. It will collect digits
 * into numbers, and pass operations to the controller.
 */
- (void) handleCommand: (NSString *) command {
	NSLog(@"BasicCalculatorView handleCommand: [%@] display=[%@]", command, display);

	// The view collects its own digits and decimal 
	// separators into a complete "entry" number before
	// passing it along to the controller.
	// This releives the model/controller from doing this
	// work that I don't think it should do anyhow.
	// TODO check for multiple decimal points and dont allow.
	if ([command length] == 1) {
		char cmd = [command characterAtIndex: 0];
		if (isdigit(cmd) || (cmd == '.')) {
			// reset the display to blank when we hit
			// our first digit of an entry.
			if (resetDisplay == YES) {
				[display setString: @""];
			}
			
			[display appendFormat: @"%c", cmd];
			[self updateView];
			
			// if we are mid-digits don't reset the display
			// on the next digit.
			resetDisplay = NO;
			return;
		}
	}
	
	// Send the collected number (if any) to the controller
	// Don't send the number if they hit two operations
	// in a row, the engine should get them just the order
	// we did.
	if (resetDisplay == NO) {
		[controller handleCommand: display];
	}
	
	// Send the collected operator to the controller
	[controller handleCommand: command];

	// indicate that what is in the display is a result
	// and a digit-decimal entry should reset it.
	resetDisplay = YES;
	
	// get the result and display it in the view
	[display setString: [engine getCurrentResult]];
	[self updateView];
}

@end
